
#include "TimerHeap.h"
pthread_cond_t    TimerHeap::m_pthreadCond = PTHREAD_COND_INITIALIZER; 
TimerHeap::TimerHeap()
{
    m_nActiveTimer 		= 0;
    m_shutdown = false;
    pthread_mutex_init(&m_ActiveMutexTimer, nullptr);
}

bool SortTimer(const heap_timer * m1, const heap_timer * m2)
{
    return m1->expire < m2->expire;
}

TimerHeap::~TimerHeap() 
{
    m_shutdown = false;
}
void TimerHeap::AddTimer(heap_timer *timer)
{
    if (!timer)
    {
        return;
    }

    pthread_mutex_lock(&m_ActiveMutexTimer);

    m_ActiveTimerList.push_back(timer);
    m_nActiveTimer++;
    
    pthread_mutex_unlock(&m_ActiveMutexTimer);

    int err = pthread_cond_signal(&m_pthreadCond); 
}
void TimerHeap::DelTimer(heap_timer *timer, bool bDeleleFromActive /*= true*/)
{
    if (!timer)
    {
        printf("....DelTimer... nullptr \n");
        return;
    }
    if (bDeleleFromActive)
    {     
        pthread_mutex_lock(&m_ActiveMutexTimer);
        std::list<heap_timer*>::iterator   iter = m_ActiveTimerList.begin();
        for (; iter != m_ActiveTimerList.end();)
        {

            if ((*iter)->m_TimerId == timer->m_TimerId)
            {
                (*iter)->callBackFunc = nullptr;               
                break;
            }
            else
            {
                ++iter;
            }
        }
        //printf("DelTimer... m_nActiveTimer size():%d\n", m_ActiveTimerList.size());
        pthread_mutex_unlock(&m_ActiveMutexTimer);
        return;
    }
    
    PutOneTimer(timer);
}

void TimerHeap::Tick() 
{
    time_t cur = time(nullptr);
    m_ActiveTimerList.sort(SortTimer);
    printf("Tick1......... m_ActiveTimerList size():%d\n", m_ActiveTimerList.size());
    while (!m_ActiveTimerList.empty())
    {
        heap_timer *timer = m_ActiveTimerList.front();
        if (timer)
        {
            if (timer->expire > cur)
            {
                printf("Tick3----------> m_TimerList size:%d\n", m_nActiveTimer);
                break;
            }
            if (timer->callBackFunc)
            {
                timer->callBackFunc(timer->user_data);
            }
            m_ActiveTimerList.pop_front();  //del timer
            m_nActiveTimer--;
            DelTimer(timer, false);
            printf("Tick2 m_TimerList size:%d\n", m_nActiveTimer);
        }
        else
        {
            printf("m_ActiveTimerList.front Error\n");
        }

    }
}

heap_timer *TimerHeap::Top()
{
    if (m_ActiveTimerList.empty())
    {
        return nullptr;
    }
    else
    {
        return m_ActiveTimerList.front();
    }
}
 
heap_timer* TimerHeap::GetOneTimer()                        //获取空闲timer;
{
	heap_timer* p_Timer = new(std::nothrow)  heap_timer;
    if (p_Timer == nullptr)
    {
        return nullptr;
    }
    else
	{
		p_Timer->expire = time(nullptr) + TIMESLOT;
	}

    return p_Timer;
}
void   TimerHeap::PutOneTimer(heap_timer* timer)    //回收一个定时器;
{
    if (timer)
    {
        delete timer;  
        timer = nullptr;
    }
    else
    {
        printf("PutOneTimer nullptr Error-------########\n");
    }
}
void   TimerHeap::FreeAllTimer()                                     //程序退出释放所有定时器;
{
    pthread_mutex_lock(&m_ActiveMutexTimer);
    while (!m_ActiveTimerList.empty())
    {
        heap_timer* timer = m_ActiveTimerList.front();
        m_ActiveTimerList.pop_front();
        if (timer)
        {
            delete  timer;
        }
    }
    pthread_mutex_unlock(&m_ActiveMutexTimer);
}
bool TimerHeap::CreateTimerThread()
{

	ThreadItemTimout* pNew;

	m_threadVector.push_back(pNew = new ThreadItemTimout(this));

	int err = pthread_create(&pNew->_Handle, nullptr, TimeOutThread, pNew);
	
    if (err != 0)
	{
		printf("CEServer::CreateTimerThread()创建线程失败，返回的错误码为%d! \n", err);
		return false;
	}

	std::vector<ThreadItemTimout*>::iterator iter;
lblfor:
	for (iter = m_threadVector.begin(); iter != m_threadVector.end(); ++iter)
	{
		if ((*iter)->ifrunning == false)
		{
			usleep(100 * 1000);
			goto lblfor;
		}
	}
	return true;
}
void  TimerHeap::Stop()
{
    m_shutdown = true;

    pthread_cond_signal(&m_pthreadCond);


    std::vector<ThreadItemTimout*>::iterator iter;

    for (iter = m_threadVector.begin(); iter != m_threadVector.end(); ++iter)
    {
        pthread_join((*iter)->_Handle, nullptr); 
    }
    m_threadVector.clear();
    FreeAllTimer();
}
void* TimerHeap::TimeOutThread(void* threadData)
{
    ThreadItemTimout* pThread = static_cast<ThreadItemTimout*>(threadData);
    TimerHeap* pThis = pThread->_pThis;
    
    pthread_t tid = pthread_self(); 
    printf("Timer ThreadFunc Begin %d\n", (int)tid);
    while (1)
    {
        if (pThis->m_shutdown == true)
        {
            break;
        }
        pthread_mutex_lock(&pThis->m_ActiveMutexTimer);
        while (pThis->m_nActiveTimer == 0 && pThis->m_shutdown == false)
        {
            printf("TimeOutThread  while----------m_nActiveTimer=0\n");
            if (pThread->ifrunning == false)
            {
                pThread->ifrunning = true;
            }
            pthread_cond_wait(&m_pthreadCond, &pThis->m_ActiveMutexTimer);        
        }
        
        pThis->Tick();                                    
        pthread_mutex_unlock(&pThis->m_ActiveMutexTimer);
        heap_timer* tmp = nullptr;
        if (tmp = pThis->Top())
        {
            time_t delay = tmp->expire - time(nullptr);
            if (delay <= 0) delay = 1;
            printf("sleep ........%d\n", delay);
            sleep(delay);
        }        
    }

    printf("TimeOutThread    Exit... \n");
    return (void*)0;
}
